import { empty } from '@/utils/test'




/**
 * @example 好像是数据去重复利用ES6 Set去重,这种方法还无法去掉“{}”空对象,并删除
 * @param {Array} arr 原数组
 * @returns {Array} 新数组
 */
export function uniqueArr(arr) {
	// Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
	arr = Array.from(new Set(arr))
	// 删除undefined
	arr.map((item, index) => {
		if ([undefined, null].includes(item)) arr.splice(index, 1)
	})
	return arr
}


// --------------------------- 以下为新增加的 ---------------------------------------------
/**
 * @example 任意格式日期处理
 * @example  {{ '2018-09-14 01:05' | formaDate(yyyy-MM-dd hh:mm:ss) }}
 * @example {{ '2018-09-14 01:05' | formaDate(yyyy-MM-dd) }}
 * @example  {{ '2018-09-14 01:05' | formaDate(MM/dd) }} 等
 * @param {string | date} value 日期或日期字串
 * @param {string} fmt 格式化字串
 * @returns  {string}
 */
export const formaDate = (value, fmt = 'yyyy-MM-dd') => {
	const date = new Date(value)
	const o = {
		'M+': date.getMonth() + 1, // 月份
		'd+': date.getDate(), // 日
		'h+': date.getHours(), // 小时
		'm+': date.getMinutes(), // 分
		's+': date.getSeconds(), // 秒
		'w+': date.getDay(), // 星期
		'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
		'S': date.getMilliseconds() // 毫秒
	}
	if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
	for (const k in o) {
		if (k === 'w+') {
			if (o[k] === 0) {
				fmt = fmt.replace('w', '周日')
			} else if (o[k] === 1) {
				fmt = fmt.replace('w', '周一')
			} else if (o[k] === 2) {
				fmt = fmt.replace('w', '周二')
			} else if (o[k] === 3) {
				fmt = fmt.replace('w', '周三')
			} else if (o[k] === 4) {
				fmt = fmt.replace('w', '周四')
			} else if (o[k] === 5) {
				fmt = fmt.replace('w', '周五')
			} else if (o[k] === 6) {
				fmt = fmt.replace('w', '周六')
			}
		} else if (new RegExp('(' + k + ')').test(fmt)) {
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k])
				.length)))
		}
	}
	return fmt
}

/**
 * @example  格式化分钟
 * @param {number} minutes 格式化分钟 单位：分钟
 * @returns {string} 字串'X天X时X分'
 */
export function formatMinutes(minutes) {
	// 转为数字
	minutes = Math.round(minutes)
	// 存天 、 小时 、分钟
	const res = []
	// 计算出天数
	const day = Math.floor(minutes / (60 * 24))
	minutes = minutes % (60 * 24)
	// 计算出小时数
	const hours = Math.floor(minutes / 60)
	// 计算出分钟数
	minutes = Math.round(minutes % 60)
	if (day > 0) res.push(`${day}天`)
	if (hours > 0) res.push(`${hours}时`)
	if (minutes > 0) res.push(`${minutes}分`)
	return res.join('')
}

/**
 * @example 格式化时间长度
 * @param {string} unit 时间单位 minutes分钟(默认) | second 秒
 * @param {Number}  duration 格式化的时间长度
 * @returns {string} 字串'X天X时X分X秒'
 */
export function formatDuration(duration, unit = 'minutes') {
	// 时间长度
	const DURATION = {
		DAY: unit === 'minutes' ? (24 * 60) : (24 * 60 * 60),
		HOURS: unit === 'minutes' ? 60 : (60 * 60),
		MINUTES: unit === 'minutes' ? 1 : 60
	}
	const {
		DAY,
		HOURS,
		MINUTES
	} = DURATION
	// 存天 、 小时 、分钟、秒
	const res = []
	// 转为数字
	duration = Math.round(duration)
	// 计算出天数
	const day = Math.floor(duration / DAY)
	if (day > 0) res.push(`${day}天`)
	// 减去天数后剩余的
	duration = duration % DAY
	// 计算出小时数
	const hours = Math.floor(duration / HOURS)
	if (hours > 0) res.push(`${hours}时`)
	// 减去小时数剩余的
	duration = duration % HOURS
	// 计算出分钟数
	const minutes = Math.floor(duration / MINUTES)
	if (minutes > 0) res.push(`${minutes}分`)
	// 如果单位是分钟，则无秒,直接返回
	if (unit === 'minutes') return res.join('')
	// 减去分钟数剩余的
	duration = Math.round(duration % 60)
	if (duration > 0) res.push(`${duration}秒`)
	return res.join('')
}

/**
 * @example 两个数组的并集
 * @param {Array} a = [1, 2, 3]
 * @param {Array} b = [2, 4, 5]
 * @returns {Array} [1,2,3,4,5]
 */
export const union = (a, b) => {
	return a.concat(b.filter(v => !a.includes(v)))
}

/**
 * @example 两个数组的交集
 * @param {Array} a = [1, 2, 3]
 * @param {Array} b = [2, 4, 5]
 * @returns {Array} [2]
 */
export const intersection = (a, b) => {
	return a.filter(v => b.includes(v))
}

/**
 * @example 两个数组的 差集
 * @param {Array} a = [1, 2, 3]
 * @param {Array} b = [2, 4, 5]
 * @param {String} type 结果类型 a=结果是a中的 [1,3]; b=结果是b中的 [4, 5]  ;all = [1,3,4, 5]
 * @returns {Array} 根据type类型返回数组
 */
export const differenceNew = (a, b, type = 'a') => {
	const concat = a.concat(b)
	const A = concat.filter(v => a.includes(v) && !b.includes(v))
	const B = concat.filter(v => b.includes(v) && !a.includes(v))
	if (type === 'a') return A
	if (type === 'b') return B
	return [...A, ...B]
}

/**
 * @example 功能：在数组对像中查找出指定数值所在的索引
 * @param {array} arr 要查找的数组集
 * @param {any} searchValue  要查找值
 * @param {string} key  要查找对像的键名
 * @returns {number} 找到返回索引，没有找到返回-1
 */
export const indexForObjArr = (arr, searchValue, key = 'id') => {
	let res = -1
	for (let index = 0, len = arr.length; index < len; index++) {
		const item = arr[index]
		if (item[key] == searchValue) {
			res = index
			break
		}
	}
	return res
}






/**
 * @example 对像变为数组对像
 * @param {Object} Obj 由{client: '客户'}
 * @param {Object} prop 自定义对象数组的key 、value
 * @returns {Array} 返回[{text: '客户',value: 'client'}]
 */
export const objToArr = (Obj, prop = {
	text: 'text',
	value: 'value'
}) => {
	const res = []
	Object.keys(Obj).map(key => {
		if (![undefined, null, 'undefined', 'null'].includes(key)) {
			res.push({
				[prop.text]: Obj[key],
				[prop.value]: key
			})
		}
	})
	return res
}

/**
 * @example 数组对像转为对像
 * @param {Array} arr [{text: '客户',value: 'client'}]
 * @param {Object} prop 自定义对象数组的key 、value
 * @returns {Object} 返回 {client: '客户'}
 */
export const arrToObj = (arr, prop = {
	key: 'key',
	value: 'value'
}) => {
	const {
		key,
		value
	} = prop
	const res = {}
	arr.map(item => {
		const itemKey = item[key]
		const itemValue = item[value]
		if (itemKey && itemValue) {
			Object.assign(res, {
				[itemKey]: itemValue
			})
		}
	})
	return res
}

/**
 * @example 格式化处理字符串
 * @example ecDo.formatText('1234asda567asd890') result："12,34a,sda,567,asd,890"
 * @example ecDo.formatText('1234asda567asd890',4,' ') result："1 234a sda5 67as d890"
 * @example ecDo.formatText('1234asda567asd890',4,'-') result："1-234a-sda5-67as-d890"
 * @param {String} str 字符串
 * @param {Number} size 几个字串一组
 * @param {String} delimiter 分割符号
 * @returns {String} 字符串
 */
export const formatText = (str, size = 3, delimiter = ',') => {
	const regText = '\\B(?=(\\w{' + size + '})+(?!\\w))'
	const reg = new RegExp(regText, 'g')
	return str.replace(reg, delimiter)
}


/**
 * @example 获取文件后缀名
 * @param {string} fileName 文件名
 * @returns {string} 后缀名
 */
export const fileExtension = (fileName) => {
	const index = fileName.lastIndexOf('.')
	return index === -1 ? '' : fileName.slice(index + 1)
}

/**
 * @example 参数说明：新对像的与旧对像是否不同,传入必copy,否则改变了原对像
 * @param {Object} newObj 新对像
 * @param {Object} oldObj 旧对像
 * @returns  {Object | Boolean} 有不同返加不同的对像，一样返回false
 */
export const imparity = (newObj, oldObj) => {
	const newO = clone(newObj)
	const oldO = clone(oldObj)
	const res = {}
	Object.keys(newObj).map(key => {
		let newItem = newO[key]
		let oldItem = oldO[key]
		// 如是对像或数组，则转成json字串后比较
		if (typeof (newItem) === 'object') newItem = JSON.stringify(newItem)
		if (typeof (oldItem) === 'object') oldItem = JSON.stringify(oldItem)
		if (newItem !== oldItem) {
			res[key] = newObj[key]
		}
	})
	return empty(res) ? false : res
}

/**
 * @example 参数说明：新对像的与旧对像是否一样,
 * @param {Object} newObj 新对像
 * @param {Object} oldObj 旧对像
 * @returns  {Boolean} 一样返回ture ,否则false
 */
export const uniformity = (newObj, oldObj) => {
	return !imparity(newObj, oldObj)
}

/**
 * @example A对像是否包含B对像,
 * @param {Object}  A对像
 * @param {Object} B对像
 * @returns {Boolean} 包含返回ture ,否则false
 */
export const include = (aObj, bObj) => {
	return !imparity(bObj, aObj)
}


/**
 * @example 去除对像中数值为空的键
 * @param {Object}  oldObj 原对像
 * @param {Object}  alias  别名 {oldKey:newKey}
 * @param {Array}  required 必须要有的键,是原对像的键 ['oldKey']
 * @param {Boolean}  req 返回必须有的键却无此键
 * @returns {Object} 新对像 {data:'新对像',required:['无必须的oldKey']}
 */
export const delEmptyValue = (oldObj, {
	alias = {},
	required = [],
	req = false
} = {}) => {
	// 去除空字串
	const res = {};
	// 必须要有的键为空时
	const must = []
	Object.keys(oldObj).map(key => {
		const value = oldObj[key]
		if (empty(value)) {
			if (Array.isArray(required) && required.includes(key)) {
				must.push(key)
				console.warn(`${key}键是必须有数值的.`)
			}
			return
		}
		// 把 原来的Key 转变新的 Key
		const newKey = alias[key]
		if (newKey) key = newKey
		res[key] = value
	})
	return req ? clone({
		data: res,
		required: must.length > 0 ? must : ''
	}) : clone(res)
}

/**
 * @example 首字母大写
 * @example 使用slice()方法将字符串分成两部分：首字母字符部分，和其他子字符部分。
 * @example 使用toUpperCase()方法将首字母转换为大写；使用toLowerCase()将其他子字符转换为小写。
 * @example 使用“+”运算符，将两个部分重新拼接起来.toLowerCase();
 * @param {string} str 字串
 * @returns  {string} str 字串
 */

export const headCase = (str) => {
	const newStr = str.slice(0, 1).toUpperCase() + str.slice(1)
	return newStr
}

/**
 * @example 字母大小写切换
 * @param {Number} type 1:首字母大写
 *                      2：首页母小写
 *                      3：大小写转换
 *                      4：全部大写
 *                      5：全部小写
 * @returns  {string} str 字串
 */

export const changeCase = (str, type) => {
	function ToggleCase(str) {
		let itemText = ''
		str.split('').forEach(
			function (item) {
				if (/^([a-z]+)/.test(item)) {
					itemText += item.toUpperCase()
				} else if (/^([A-Z]+)/.test(item)) {
					itemText += item.toLowerCase()
				} else {
					itemText += item
				}
			})
		return itemText
	}
	switch (type) {
		case 1:
			return str.replace(/\b\w+\b/g, function (word) {
				return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase()
			})
		case 2:
			return str.replace(/\b\w+\b/g, function (word) {
				return word.substring(0, 1).toLowerCase() + word.substring(1).toUpperCase()
			})
		case 3:
			return ToggleCase(str)
		case 4:
			return str.toUpperCase()
		case 5:
			return str.toLowerCase()
		default:
			return str
	}
}

/**
 * @example  深度克隆,不抛出错误
 * @param {*} obj 对像
 * @returns {*} 如传入对像,则深度克隆,否则原样返回
 */
export const clone = (obj) => {
	return typeof (obj) === 'object' ? JSON.parse(JSON.stringify(obj)) : obj
}
















/**
 * @example 判断是否为空
 * @returns {boolean}  空=false  ,非空true
 */
export const isNotEmpty = (str) => {
	return !empty(str)
};

// JS过滤HTML标签
export const filterHTMLTag = (msg) => {
	var msg = msg.replace(/<\/?[^>]*>/g, ''); //去除HTML Tag
	msg = msg.replace(/[|]*\n/, '') //去除行尾空格
	msg = msg.replace(/&npsp;/ig, ''); //去掉npsp
	return msg;
}

/**
 * @example 对象转url参数
 * @param {Object} data
 * @param {Boolean} isPrefix 前缀问号
 * @returns {String}  微信小程序不能把encodeURI 自动转为汉字 decodeURIComponent
 */
export const urlEncode = (data, isPrefix = false) => {
	const prefix = isPrefix ? '?' : ''
	const _result = []
	for (const key in data) {
		const value = data[key]
		// 去掉为空的参数
		if ([undefined, null].includes(value)) {
			continue
		}
		// 如果value是数组，或对像，须要转成 json 字串
		if (typeof (value) === 'object') {
			// #ifdef H5
			_result.push(encodeURIComponent(key) + '=' + encodeURIComponent(JSON.stringify(value)))
			// #endif
			// #ifndef H5
			_result.push(key + '=' + JSON.stringify(value))
			// #endif
		} else {
			// 如果是还是对像，则
			// #ifdef H5
			_result.push(encodeURIComponent(key) + '=' + encodeURIComponent(value))
			// #endif
			// #ifndef H5
			_result.push(key + '=' + value)
			// #endif
		}
	}
	return _result.length ? prefix + _result.join('&') : ''
}


//去除空格 type 1-所有空格 2-前后空格 3-前空格 4-后空格
export const trim = (value, trim) => {
	switch (trim) {
		case 1:
			return value.replace(/\s+/g, "");
		case 2:
			return value.replace(/(^\s*)|(\s*$)/g, "");
		case 3:
			return value.replace(/(^\s*)/g, "");
		case 4:
			return value.replace(/(\s*$)/g, "");
		default:
			return value;
	}
}



//字符串循环复制,count->次数
export const repeatStr = (str, count) => {
	let text = '';
	for (let i = 0; i < count; i++) {
		text += str;
	}
	return text;
}
//字符串替换
export const replaceAll = (str, AFindText, ARepText) => {
	raRegExp = new RegExp(AFindText, "g");
	return str.replace(raRegExp, ARepText);
}
//字符替换*，隐藏手机号或者身份证号等
//replaceStr(字符串,字符格式, 替换方式,替换的字符（默认*）)
//ecDo.replaceStr('18819322663',[3,5,3],0)
//result：188*****663
//ecDo.replaceStr('asdasdasdaa',[3,5,3],1)
//result：***asdas***
//ecDo.replaceStr('1asd88465asdwqe3',[5],0)
//result：*****8465asdwqe3
//ecDo.replaceStr('1asd88465asdwqe3',[5],1,'+')
//result："1asd88465as+++++"
export const replaceStr = (str, regArr, type, ARepText) => {
	let regtext = '',
		Reg = null,
		replaceText = ARepText || '*';
	//repeatStr是在上面定义过的（字符串循环复制），大家注意哦
	if (regArr.length === 3 && type === 0) {
		regtext = '(\\w{' + regArr[0] + '})\\w{' + regArr[1] + '}(\\w{' + regArr[2] + '})'
		Reg = new RegExp(regtext);
		let replaceCount = this.repeatStr(replaceText, regArr[1]);
		return str.replace(Reg, '$1' + replaceCount + '$2')
	} else if (regArr.length === 3 && type === 1) {
		regtext = '\\w{' + regArr[0] + '}(\\w{' + regArr[1] + '})\\w{' + regArr[2] + '}'
		Reg = new RegExp(regtext);
		let replaceCount1 = this.repeatStr(replaceText, regArr[0]);
		let replaceCount2 = this.repeatStr(replaceText, regArr[2]);
		return str.replace(Reg, replaceCount1 + '$1' + replaceCount2)
	} else if (regArr.length === 1 && type === 0) {
		regtext = '(^\\w{' + regArr[0] + '})'
		Reg = new RegExp(regtext);
		let replaceCount = this.repeatStr(replaceText, regArr[0]);
		return str.replace(Reg, replaceCount)
	} else if (regArr.length === 1 && type === 1) {
		regtext = '(\\w{' + regArr[0] + '}$)'
		Reg = new RegExp(regtext);
		let replaceCount = this.repeatStr(replaceText, regArr[0]);
		return str.replace(Reg, replaceCount)
	}
}




// 获取最小值到最大值之前的整数随机数
export const getRandomNum = (Min = 0, Max = 100) => {
	let Range = Max - Min;
	let Rand = Math.random();
	// round() 方法可把一个数字舍入为最接近的整数
	return (Min + Math.round(Rand * Range));
}
// JS生成随机字符串的方法 指定长度  flag=长度

export const randomWord = (flag = 3) => {
	let str = "",
		arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
			'k', 'l',
			'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
			'H', 'I',
			'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
		];

	for (let i = 0; i < flag; i++) {
		let pos = Math.round(Math.random() * (arr.length - 1));
		str += arr[pos];
	}
	return str;
}